package jwlee.testxml;

import java.io.File;
import java.io.StringReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Properties;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import jwlee.testfile.FileReader;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
import org.dom4j.io.SAXReader;

/**
 * 
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright:  Copyright (c) 2010</p>
 * <p>Company: DC </p>
 * 
 * @author lijwg
 * @date 2011-3-28
 * @version 1.0
 */
public class XmlXsl2Html {

	/**
	 * 读文件转换
	 * 
	 * @param xmlFileName
	 * @param xslFileName
	 * @param htmlFileName
	 * @throws TransformerException
	 */
	public static void transformByFile(File xslFile, File xmlFile, File htmlFile)
			throws TransformerException {
		Source xslSource = new StreamSource(xslFile);
		Transformer transformer = TransformerFactory.newInstance()
				.newTransformer(xslSource);

		Source xmlSource = new StreamSource(xmlFile);

		Result htmlResult = new StreamResult(htmlFile);

		transformer.transform(xmlSource, htmlResult);
	}

	/**
	 * 读字符串转换
	 * 
	 * @param xmlStr
	 * @param xslStr
	 * @return
	 * @throws TransformerException
	 * @throws DocumentException
	 */
	public static String transformByStr(String xslStr, String xmlStr)
			throws TransformerException, DocumentException {
		StreamSource xslSource = new StreamSource(new StringReader(xslStr));
		Transformer transformer = TransformerFactory.newInstance()
				.newTransformer(xslSource);//weblogic.xml.jaxp.RegistrySAXTransformerFactory
		Properties properties = transformer.getOutputProperties();
		properties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		properties.setProperty(OutputKeys.ENCODING, "utf-8");
		properties.setProperty(OutputKeys.METHOD, "html");
		properties.setProperty(OutputKeys.VERSION, "4.0");
		transformer.setOutputProperties(properties);

		Document xmlDoc = new SAXReader().read(new StringReader(xmlStr));
		DocumentSource xmlSource = new DocumentSource(xmlDoc);

		DocumentResult htmlResult = new DocumentResult();

		transformer.transform(xmlSource, htmlResult);

		return htmlResult.getDocument().asXML();// .getDocument().getText();
	}

	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println(4001l/2000l + (4001l%2000l>0?1:0));
		testTransByStr();
		// testTransByFile();
	}


	private static void testTransByFile() {
		String xslFileName = "src/jwlee/testxml/xsl.xsl";
		String xmlFileName = "src/jwlee/testxml/xml.xml";
		String htmlFileName = "src/jwlee/testxml/html.html";
		File xslFile = new File(xslFileName);
		File xmlFile = new File(xmlFileName);
		File htmlFile = new File(htmlFileName);
		try {
			transformByFile(xslFile, xmlFile, htmlFile);
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}
	
	private static void testTransByStr() {
		String xslFileName = "src/jwlee/testxml/xsl2.xsl";
		String xmlFileName = "src/jwlee/testxml/xml2.xml";
		try {
			String xslFileStr = FileReader.read(xslFileName, "GBK");
			xslFileStr = processXsl(xslFileStr);
			System.out.println("xsl:\n" + xslFileStr);
			
			String xmlFileStr = FileReader.read(xmlFileName, "GBK");
//			System.out.println("\nxml:\n" + xmlFileStr);
			
			String htmlStr = transformByStr(xslFileStr, xmlFileStr);
			htmlStr = processHtml(htmlStr);
			System.out.println("\nresult:\n" + htmlStr);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	private static String processXsl(String xslStr) {
		StringBuffer xslBuff = new StringBuffer();
		char[] xslchars = xslStr.toCharArray();
		int doStylesheeTag = 0;// 不同位置的三个状态：0 <xsl:styleshee 1 > 2
		boolean jsBegin = false, jsEnd = false;// [f,f] <xsl:script [t,f] </xsl:script> [f,t]
		int numOfJsTag = 0;// 为了就判断一次,前提是只有一个js标签
		int formatNumTag = 0;//0 formatNum1("2YSBHC"0,"#,##0")
		boolean evalBegin = false;// 去除eval标签
		boolean bTrimBegin = false;
		for (int i = 0; i < xslchars.length; i++) {
			//  <?xml version="1.0"?>必须打头且顶格
			if (!bTrimBegin && !"<".equals("" + xslchars[i])) {
				continue;
			} else if ("<".equals("" + xslchars[i])) {
				bTrimBegin = true;
			}
			
			// 处理xsl:styleshee标签，不然无法解析
			if (doStylesheeTag < 2) {
				if (doStylesheeTag == 0
						&& i + 13 < xslchars.length
						&& "<xsl:styleshee".equals("" + xslchars[i]
								+ xslchars[i + 1] + xslchars[i + 2]
								+ xslchars[i + 3] + xslchars[i + 4]
								+ xslchars[i + 5] + xslchars[i + 6]
								+ xslchars[i + 7] + xslchars[i + 8]
								+ xslchars[i + 9] + xslchars[i + 10]
								+ xslchars[i + 11] + xslchars[i + 12]
								+ xslchars[i + 13])) {
					doStylesheeTag = 1;
					i += 13;
					continue;
				} else if (doStylesheeTag == 1) {
					if (">".equals("" + xslchars[i])) {
						xslBuff
								.append("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">");
						doStylesheeTag = 2;
					}
					continue;
				}
			}
			
			//按js标签将xsl分三段处理
			if (!jsBegin && !jsEnd) {
				if (numOfJsTag == 0 && i + 10 < xslchars.length
						&& "<xsl:script".equals("" + xslchars[i]
								+ xslchars[i + 1] + xslchars[i + 2]
								+ xslchars[i + 3] + xslchars[i + 4]
								+ xslchars[i + 5] + xslchars[i + 6]
								+ xslchars[i + 7] + xslchars[i + 8]
								+ xslchars[i + 9] + xslchars[i + 10])) {
					jsBegin = true;
					i += 12;// 跳过
					continue;
				}
			} else if (jsBegin && !jsEnd) {
				if (numOfJsTag == 0 && i + 12 < xslchars.length
						&& "</xsl:script>".equals("" + xslchars[i]
								+ xslchars[i + 1] + xslchars[i + 2]
								+ xslchars[i + 3] + xslchars[i + 4]
								+ xslchars[i + 5] + xslchars[i + 6]
								+ xslchars[i + 7] + xslchars[i + 8]
								+ xslchars[i + 9] + xslchars[i + 10]
								+ xslchars[i + 11] + xslchars[i + 12])) {
					jsBegin = false;
					jsEnd = true;
					i += 12;// 跳过
					numOfJsTag++;
					continue;
				}
				continue;// 忽略
			} else if (!jsBegin && jsEnd) {
				// formatNum("YSBHC","#,##0") -> formatNum("<xsl:value-of select='./YSBHC'/>","#,##0")
				if (formatNumTag == 0 && i + 8 < xslchars.length && "formatNum".equals("" + xslchars[i] + xslchars[i + 1]
						+ xslchars[i + 2] + xslchars[i + 3] + xslchars[i + 4]
						+ xslchars[i + 5] + xslchars[i + 6] + xslchars[i + 7]
						+ xslchars[i + 8])) {
					formatNumTag = 1;
				} else if (formatNumTag == 1 && "\"".equals("" + xslchars[i])) {
					formatNumTag = 2;
					xslBuff.append("\"<xsl:value-of select=\"./");
					continue;
				} else if (formatNumTag == 2 && "\"".equals("" + xslchars[i])) {
					formatNumTag = 0;
					xslBuff.append("\"/>");
				}
			}
			
			if (!evalBegin
					&& i + 9 < xslchars.length
					&& "<xsl:eval>".equals("" + xslchars[i] + xslchars[i + 1]
							+ xslchars[i + 2] + xslchars[i + 3]
							+ xslchars[i + 4] + xslchars[i + 5]
							+ xslchars[i + 6] + xslchars[i + 7]
							+ xslchars[i + 8] + xslchars[i + 9])) {
				i += 9;
				evalBegin = true;
				continue;
			} else if (evalBegin
					&& i + 10 < xslchars.length
					&& "</xsl:eval>".equals("" + xslchars[i] + xslchars[i + 1]
							+ xslchars[i + 2] + xslchars[i + 3]
							+ xslchars[i + 4] + xslchars[i + 5]
							+ xslchars[i + 6] + xslchars[i + 7]
							+ xslchars[i + 8] + xslchars[i + 9]
							+ xslchars[i + 10])) {
				i += 10;
				evalBegin = false;
				continue;
			}
			
			xslBuff.append(xslchars[i]);
		}

		return xslBuff.toString();
	}
	
	//处理js
	private static String processHtml(String htmlStr){
		StringBuffer htmlBuff = new StringBuffer();
		char[] htmlchars = htmlStr.toCharArray();
		int formatNumTag = 0;//0 formatNum1("2 5555"3,"4#,##0"0)
		StringBuffer numBuf = new StringBuffer();
		StringBuffer formatBuf = new StringBuffer();
		int count = 1;// 处理count()
		for (int i = 0; i < htmlchars.length; i++) {
			if (formatNumTag == 0
					&& i + 8 < htmlchars.length
					&& "formatNum".equals("" + htmlchars[i] + htmlchars[i + 1]
							+ htmlchars[i + 2] + htmlchars[i + 3]
							+ htmlchars[i + 4] + htmlchars[i + 5]
							+ htmlchars[i + 6] + htmlchars[i + 7]
							+ htmlchars[i + 8])) {
				formatNumTag = 1;
				numBuf.delete(0, numBuf.length());
				formatBuf.delete(0, formatBuf.length());
			} else if (formatNumTag == 1 && "\"".equals("" + htmlchars[i])) {
				formatNumTag = 2;
			} else if (formatNumTag == 2 && !"\"".equals("" + htmlchars[i])) {
				numBuf.append(htmlchars[i]);
			} else if (formatNumTag == 2 && "\"".equals("" + htmlchars[i])) {
				formatNumTag = 3;
			} else if (formatNumTag == 3 && "\"".equals("" + htmlchars[i])) {
				formatNumTag = 4;
			} else if (formatNumTag == 4 && !"\"".equals("" + htmlchars[i])) {
				formatBuf.append(htmlchars[i]);
			} else if (formatNumTag == 4 && "\"".equals("" + htmlchars[i])) {
				formatNumTag = 0;
				String numStr = numBuf.toString();
				String formatStr = formatBuf.toString();
//				System.out.println(formatStr+" : "+numStr);
				try {
					DecimalFormat df = new DecimalFormat(formatStr);
					numStr = df.format(new BigDecimal(numStr));
				} catch (Exception e) {
					System.err.println("格式化异常: " + numStr + " , " + formatStr);
				}
				htmlBuff.append(numStr);
				i++;// 跳过 )
			} else if (formatNumTag == 0) {
				if (i + 6 < htmlchars.length
						&& "count()".equals("" + htmlchars[i]
								+ htmlchars[i + 1] + htmlchars[i + 2]
								+ htmlchars[i + 3] + htmlchars[i + 4]
								+ htmlchars[i + 5] + htmlchars[i + 6])) {
					i += 6;
					htmlBuff.append("" + count++);
					continue;
				}
				htmlBuff.append(htmlchars[i]);
			}
		}
		return htmlBuff.toString();
	}
}
